Cette section va être un peu longue, je vous préviens. Elle couvre enfin le concept le plus important de Java et il y a beaucoup de choses à raconter ici... Bonne lecture !
Java est un langage de programmation orienté objet. Ça signifie que les données peuvent être représentées sous formes d'objets. Un objet peut contenir de la donnée, avoir un comportement prédéfini, les objets peuvent interagir les uns avec les autres...
Dans la section dédiée aux types j'ai évoqué deux catégories de types :
int
, double
, boolean
, ...)String
, List
, Object
, ...)Les premiers sont au nombre de 8. En revanche, il existe potentiellement une infinité de types objets. Pourquoi ? Parce que vous pouvez créer les vôtres !
Certains sont fournis par le JDK, comme ceux listés juste au dessus (et bien plus encore !), d'autres seront créés par vous pour vos besoins, d'autres encore pourront venir d'outils mis à dispositions par d'autres développeurs. On appelle ça des librairies. On évoquera ce sujet plus tard.
À quoi servent ces types objets ?
Bon, jusque là nos données étaient assez simples, les types primitifs faisaient l'affaire pour compter ou afficher du texte, mais je vais prendre un exemple un peu plus poussé :
Imaginez que vous devez représenter un livre. Il n'y a pas de type Book pour faire ça, alors on va le créer !
Pour ça, il y a deux façons de faire : créer une classe ou créer un record. On va voir les deux manières et leurs différences.
Commençons par la classe :
Pour déclarer une nouvelle classe on va réutiliser le clic-droit sur le dossier src > new > Java Class :
On va l'appeler Book :
Et voilà le résultat :
public class Book { }
On va pouvoir écrire le contenu de la classe entre les accolades.
public class Book {
// en dessous on trouve les attributs
private final String title;
private final String author;
private final int releaseYear = 2025;
// ici on trouve le constructeur
public Book(String title, String author, int releaseYear) {
this.title = title;
this.author = author;
this.releaseYear = releaseYear;
}
// à partir de là ce sont les méthodes
public Book getOldest(Book other) {
if (this.releaseYear > other.releaseYear) {
return this;
} else {
return other;
}
}
@Override
public String toString() {
return this.title + " written by " + this.author + " in " + this.releaseYear;
}
}
Une classe est composée de plusieurs petits trucs intéressants à voir :
Commençons par décrire ce qui caractérise un livre : son titre, son auteur et son année de parution. (On pourrait penser à tout un tas d'autres trucs comme l'éditeur ou l'ISBN mais on va pas pousser trop loin pour notre exemple)
Chacune de ses caractéristiques devient un attribut de la classe (qu'on appelle aussi des champs). Ces attributs se comportent comme des variables dans notre programme mais peuvent avoir des modificateurs que l'on détaillera juste après.
Ainsi, le titre sera représenté par un attribut title de type String
, l'auteur sera représenté par un attribut author de type String
et enfin l'année de parution sera représentée par un attribut releaseYear de type int
.
Pour initialiser les attributs de notre classe nous avons 3 possibilités :
2025)Voilà à quoi ressemble un constructeur :
public Book(String title, String author, int releaseYear) {
this.title = title;
this.author = author;
this.releaseYear = releaseYear;
}
En soit, c'est un peu comme une méthode qui prend des paramètres et qui initialise nos attributs !
Bon, détaillons un peu plus ce que c'est :
public
, c'est un modificateur (qu'on abordera après)Bon, si vous êtes attentifs, vous aurez remarqué qu'il y a un nouveau mot en gras sur la dernière ligne : instance.
Une classe Book n'est rien que la représentation d'un livre. Si on veut vraiment créer un livre dans notre code il va falloir déclarer et initialiser une variable de type Book comme ceci :
Book myBook = new Book("Le Petit Prince", "Antoine de Saint-Exupéry", 1943);
C'est un peu plus laborieux de construire un Book qu'un int mais c'est assez logique, il y a plus de complexité et plein d'attributs à initialiser alors analysons cette ligne de code.
On découvre le mot clé new
qui permet de créer un objet en appelant son constructeur. Le constructeur appelé est celui déclaré dans la classe, qui prend 3 paramètres pour le titre, l'autheur et l'année de parution. Le tout initialise une instance de Book qui est stockée dans notre variable myBook
!
Donc si on récapitule, une classe c'est la représentation d'un objet, et une instance c'est un exemplaire concret de notre classe dans notre programme.
On peut faire référence aux attributs de l'instance avec le mot clé this
. Donc ici le constructeur initialise les attributs de notre instance avec les valeurs des paramètre donnés au constructeur.
this.title = title; // initialise l'attribut this.title de l'instance avec le paramètre title
this.author = author;
this.releaseYear = releaseYear;
Grâce à ça, les attributs de l'instance myBook
sont bien initialisés avec les valeurs données au constructeur !
Les méthodes d'une classe servent à manipuler ses attributs.
La méthode public Book getOldest(Book other)
sert à comparer notre livre (this) avec un autre livre donné en paramètre (other). Elle renvoie celui des deux qui est le plus ancien en fonction de son année de parution.
La méthode public String toString()
permet d'afficher proprement une instance de Book
sous forme de texte. C'est une méthode que toutes les classes ont sans exceptions. C'est grâce à cette méthode que vous verrez votre variable s'afficher proprement dans la console si vous utilisez println()
!
Je les ai déjà évoqué à quelques reprises, les modificateurs ont leur rôle à jouer. Ils peuvent intervenir au niveau de la classe, de ses attributs, ses méthodes ou même ses constructeurs.
Les modificateurs permettent d'indiquer à Java des comportements spécifiques de nos classes, leurs méthodes, leurs constructeurs et de leurs attributs. Techniquement vous en aviez déjà utilisé sur la déclaration de la classe sans y prêter attention : public class Book {
.
public
est un modificateur d'accès qui veut dire que la classe est publique.
Le titre sera représenté par une variable title de type String
, l'auteur sera représenté par une variable author de type String
et enfin l'année de parution sera représentée par une variable year de type int
.
En programmation orientée objet, les variables qui caractérisent une classe sont appelée des attributs (ou aussi des champs).
En Java, on déclare les attributs d'une classe comme ceci :
public class Book {
// [modificateurs] type nomAttribut [= valeur par défaut];
}
C'est assez similaire à la déclaration de variable dans le main mais il y a une notion de modificateurs en plus. On verra ce que ça veut dire dans un instant.
Pour l'instant je vais coder mon exemple et vous comprendrez au fur et à mesure du chapitre.
Alors je disais, déclarons les attributs d'un livre :
public class Book {
private final String title;
private final String author;
private final int year;
}
Si vous laissez votre code dans l'état, votre IDE va râler avec un message dans le genre Variable 'title' might not have been initialized et ainsi de suite pour les attributs author et year.
C'est normal, c'est à cause du modificateur final
! La partie dédiée aux modificateurs plus bas entrera plus dans les détails. Pour l'instant on va avancer.
Il existe deux façons de corriger l'erreur que nous indique l'IDE :
Je ne vois pas de valeur par défaut évidente dans notre cas alors on va partir sur le constructeur.
La machine doit être capable de servir différents types de cafés (expresso, capuccino...) mais aussi des boissons chocolatées ! La quantité de sucre doit pouvoir être réglée par l'utilisateur.
La machine contient un stock de gobelets, de touillettes et d'ingrédients pour pouvoir servir l'utilisateur... Bref, il y a tout un tas de choses à prendre en compte dans un appareil qui semble pourtant si évident à utiliser !
Autant vous dire que les simple types primitifs vont pas beaucoup nous aider pour un problème aussi complexe. À moins que ?
À moins qu'on soit capable de les assembler pour représenter quelque chose de plus complexe !
C'est exactement le principe des classes. On va pouvoir représenter des données complexes et les manipuler à travers un assemblage d'informations et d'intéractions codées dans la classe !
Ok, reprenons notre problèmes de machine à café. Voici les informations que la machine à besoin de représenter :